﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CrazyWorship1.ListenerService;
using System.IO;
using System.Xml.Serialization;
using System.ServiceModel;
using System.Reflection;
using System.Collections.ObjectModel;

namespace CrazyWorship1
{


    
    /// <summary>
    /// Interaction logic for ClientManager.xaml
    /// </summary>
    public partial class ClientManager
    {
        public ClientManager()
        {
            clients = new Dictionary<string, BaseListenerClient>();
            ds = new ClientList();
            LoadClients();
        }
        ClientList ds;
        public static string clientsFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "//CrazyWorship";
        public static string clientsFile = clientsFolder + "//clients.dat";
        public static string screenInfoFile = clientsFolder + "//screenInfo.dat";
        public static string screenFile = clientsFolder + "//screen.dat";
     
        Dictionary<string, BaseListenerClient> clients;
        public ClientList ClientList
        {
            get
            {
                return ds;
            }
        }



        public List<BaseListenerClient> ConnectedClients
        {
            get
            {
                List<BaseListenerClient> cl=new List<BaseListenerClient>();
                foreach (Client c in ClientList)
                {
                    if (c.Connected)
                    {
                        cl.Add(clients[c.ClientUrl]);
                    }

                }
                return cl;
            }
        }
        public void LoadClients()
        {
            if (!Directory.Exists(clientsFolder))
                Directory.CreateDirectory(clientsFolder);
            //    ds.LoadClients();
            ds.Clear();
            clients.Clear();
            FileStream stream = new FileStream(clientsFile, FileMode.OpenOrCreate);
            try
            {
                XmlSerializer x = new XmlSerializer(typeof(ClientList));

                ClientList temp = (ClientList)x.Deserialize(stream);
                foreach (Client c in temp)
                {
                    ds.Add(c);
                    c.Parent = ds;
                }

            }
            catch (FileLoadException)
            {
                ds = new ClientList();
            }
            catch (InvalidOperationException)
            {
                ds = new ClientList();
            }
            stream.Close();

            //ds.ReadXml(clientsFile);
            foreach (Client c in ds)
            {
                BaseListenerClient baseClient;
                try
                {
                    baseClient = new BaseListenerClient("TcpChunkingBinding_IBaseListener", c.ClientUrl+"/ep1");
                    baseClient.TryConnect();
                    
                    //FileStream infile = new FileStream(
                    //"c:\\test.wmv",
                    //FileMode.Open,
                    //FileAccess.Read);
                  
                    //baseClient.SendFile(infile);
                    clients.Add(c.ClientUrl, baseClient);
                    c.Connected = true;
                }
              
                catch (InvalidOperationException)
                {
                    c.Connected = false;
                }
                catch (EndpointNotFoundException)
                {
                    c.Connected = false;
                }
                catch (CommunicationException)
                {
                    c.Connected = false;
                }
                catch (UriFormatException)
                {
                    c.Connected = false;
                }
                catch (ArgumentException)
                {
                    c.Connected = false;
                }
            }
            GetScreens();
        }
        private void GetScreens()
        {
            ds.ScreenList.Clear();
            ds.ScreenInfoList.Clear();
            foreach (Client r in ds)
            {
                if (r.Connected)
                {
                    Dictionary<Guid, Display> displays = clients[r.ClientUrl].GetCurrentDisplays();
                    ScreenInfoList lastScreenInfoList = ScreenInfoList.Load();
                    ScreenList lastScreenList = ScreenList.Load();
                    DisplayInfoList info = clients[r.ClientUrl].GetDisplayInfo();
                   
                    foreach (DisplayInfo d in info.Displays)
                    {
                        ds.ScreenInfoList.Add(r.ClientUrl, d);
                        ScreenInfo newScreenInfo = ds.ScreenInfoList.GetByClientUrl(r.ClientUrl,d.DeviceName);
                        ScreenInfo oldScreenInfo = lastScreenInfoList.GetByClientUrl(r.ClientUrl,d.DeviceName);
                        if (newScreenInfo.Equals(oldScreenInfo))
                        {
                            foreach (Screen oldScreen in lastScreenList)
                            {
                                if ((oldScreen.ClientUrl==oldScreenInfo.ClientUrl)&&(oldScreen.DeviceName==oldScreenInfo.DeviceName)&&(d.DeviceName==oldScreen.DeviceName))
                                {
                                    AddScreen(oldScreen);
                                }
                            }
                        }
                        ds.ScreenInfoList.Save();
                           

                    }
                    //ds.ScreenInfo.AddScreenInfoRow("WOW", "22,22", r);
                }
            }
        }


        private void Save()
        {
            XmlSerializer x = new XmlSerializer(typeof(ClientList));
            FileStream stream = new FileStream(clientsFile, FileMode.Create);
            x.Serialize(stream, ds);
            stream.Close();
            //ds.WriteXml(clientsFile);
        }
        public void AddClient(string url)
        {
            ds.Add(new Client(ds, url));
            Save();
            LoadClients();
        }
        public void RemoveClient(Client r)
        {
            ds.Remove(r);
            Save();
            LoadClients();
        }
        public void CloseAll()
        {
            foreach (BaseListenerClient client in clients.Values)
            {
                client.Close();
            }
            clients.Clear();
        }
        public void AddScreen(ScreenInfo monitor, Rectangle bounds)
        {
            Display a = clients[monitor.ClientUrl].AddDisplay(monitor.DeviceName, new System.Windows.Point(bounds.Left, bounds.Top), new System.Windows.Size(bounds.Width, bounds.Height));
            Screen s = ds.ScreenList.Add(a.Guid, monitor.DeviceName, monitor.ClientUrl, bounds);
            ds.ScreenList.Save();
            s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);
        }
        public void AddScreen(Screen scrn)
        {
            Display a;
            Screen s;
            if (scrn.IsFullScreen)
            {
                a = clients[scrn.ClientUrl].AddFullScreenDisplay(scrn.DeviceName);
                s = ds.ScreenList.Add(a.Guid, scrn.DeviceName, scrn.ClientUrl);
            }
            else
            {
                a = clients[scrn.ClientUrl].AddDisplay(scrn.DeviceName, new System.Windows.Point(scrn.Bounds.Left, scrn.Bounds.Top), new System.Windows.Size(scrn.Bounds.Width, scrn.Bounds.Height));
                s = ds.ScreenList.Add(a.Guid, scrn.DeviceName, scrn.ClientUrl, scrn.Bounds);
            }
            ds.ScreenList.Save();
            s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);
        }
        void s_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Screen s = ((Screen)sender);
            Point point = new Point(s.Bounds.Left, s.Bounds.Top);
            Size size = new Size(s.Bounds.Width, s.Bounds.Height);
            clients[s.ClientUrl].ModifyDisplay(s.ScreenId, point, size, s.IsFullScreen);
            ds.ScreenList.Save();
        }


        public void AddScreen(ScreenInfo monitor)
        {
            Display a = clients[monitor.ClientUrl].AddFullScreenDisplay(monitor.DeviceName);
            Screen s = ds.ScreenList.Add(a.Guid, monitor.DeviceName, monitor.ClientUrl);
            ds.ScreenList.Save();
            s.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(s_PropertyChanged);
            //  a.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(a_PropertyChanged);
        }
        public void SetScreenFull()
        {
            throw new Exception();
            //  screen.IsFullScreen = true;
        }
        public void SetScreenLocation(Point location, Size size)
        {
            throw new Exception();
            //   screen.IsFullScreen = false;
            //    screen.Location = location;
            //    screen.Size = size;
        }
        public void RemoveScreen(ScreenInfo screen)
        {
            foreach (Screen s in ds.ScreenList)
            {
                if ((screen.DeviceName == s.DeviceName) && (screen.ClientUrl == s.ClientUrl))
                {
                    ds.ScreenList.Remove(s);
                    ds.ScreenList.Save();
                }
            }

        }
        public void RemoveScreen(Screen screen)
        {
            ds.ScreenList.Remove(screen);
            ds.ScreenList.Save();
        }
        public void SetMonitor(int monitor)
        {
            throw new Exception();
            //     screen.Monitor = monitor;
        }
        public void SetName(string name)
        {
            throw new Exception();
            //    screen.Name = name;
        }
        
        public Screen GetScreen(ScreenInfo screenInfo)
        {
            foreach (Screen s in ds.ScreenList)
            {
                if ((screenInfo.DeviceName == s.DeviceName) && (screenInfo.ClientUrl == s.ClientUrl))
                    return s;

            }
            return null;
        }
    }
}
